/*
 * @(#)OrdinaryAnt.java			0.1 21/11/2010
 * Copyright (C) 2010 Grupo de Alunos abaixo
 * 
 * Universidade Federal do ABC
 * Vida Artificial - 3o quadrimestre de 2010
 * Aluno: Abner
 * Aluno: Cláudio Antônio Peanho
 * Aluno: Fabrizio Borelli
 * Aluna: Maitê Balhester
 * Aluno: Rafael Munhoz
 * Professora Dr. Karla Vittori
 * Projeto: Simulação de Colônia de Formigas (antcolonyswarm)
 * 
 * Código baseado em jheatbugs-3.0 de Timothy Howe
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.edu.ufabc.va.acs.model.agent;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import swarm.Globals;

import swarm.gui.Raster;

import br.edu.ufabc.va.acs.model.AntWorld;

/**
 * Uma formiga comum. Escolhe aleatoriamente o caminho a seguir, tendo maior
 * probabilidade o caminho que a mover para longe da colônia e contiver a maior
 * quantidade de feromônio.
 * 
 * @author Peanho
 * 
 */
public class OrdinaryAnt implements Ant {

	/** mundo da simulação */
	private final AntWorld				world;

	/** coordenadas da colonia na grade bidimensional */
	private final Point					colonyPos;

	/** indice no mapa de cores */
	private byte						colorIndex;

	/** posição atual da formiga na grade bidimensional */
	private Point						pos;

	/** indica se a formiga está procurando comida ou retornando a colônia */
	private boolean						searchingFood	= true;

	private final int					width;
	private final int					height;

	private static final List<Point>	offsetList		= Arrays.asList(
																new Point(-1,
																		-1),
																new Point(0, -1),
																new Point(1, -1),
																new Point(-1, 0),
																new Point(1, 0),
																new Point(-1, 1),
																new Point(0, 1),
																new Point(1, 1));

	public OrdinaryAnt(AntWorld world, Point colonyPos) {
		this.world = world;
		width = world.getWidth();
		height = world.getHeight();
		this.colonyPos = colonyPos;
		this.pos = new Point(colonyPos);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.edu.ufabc.va.acs.model.agent.Ant#move()
	 */
	@Override
	public synchronized void move() {
		if (searchingFood) {
			// procura feromônio na vizinhança 8-conectado
			List<Point> directionList = new ArrayList<Point>(8);
			int maxValue = 0;
			Point nextPos = new Point();
			for (Point offset : offsetList) {
				Point neighbor = new Point(pos);
				neighbor.translate(offset.x, offset.y);
				if (world.isValidPos(neighbor)) {
					int value = world.getPheromoneValueAt(neighbor);
					directionList.add(neighbor);
					if (value > maxValue) {
						maxValue = value;
						nextPos = neighbor;
					}
				}
			}
			double pheromoneFactor = (double) maxValue / 10000;
			double randomMoveProb = Globals.env.uniformDblRand
					.getDoubleWithMin$withMax(0.0, 1.0);
			if (randomMoveProb > pheromoneFactor) {
				int index = Globals.env.uniformIntRand.getIntegerWithMin$withMax(0, directionList.size()-1);
				nextPos = directionList.get(index);
			}
			if (world.isPositionEmpty(nextPos))
				world.move(this, pos, nextPos);
			if (world.isFood(pos)) {
				searchingFood = false;
				colorIndex = (byte) 202;
				world.depositOnePheromoneUnit(pos);
			}
			pos.setLocation(nextPos);
		} else {
			int dx = (colonyPos.x - pos.x);
			int dy = colonyPos.y - pos.y;
			if (dx != 0)
				dx = dx < 0 ? -1 : 1;
			if (dy != 0)
				dy = dy < 0 ? -1 : 1;
			int newX1 = pos.x + dx;
			int newY1 = pos.y + dy;
			Point p = new Point(newX1, newY1);
			world.move(this, pos, p);
			world.depositOnePheromoneUnit(pos);
			pos.move(p.x, p.y);
			if (dx == 0 && dy == 0) {
				searchingFood = true;
				colorIndex = (byte) 201;
			}
		}

	}

	@Override
	public void setInitialPosition(int x, int y) {
		this.pos = new Point(x, y);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * br.edu.ufabc.va.acs.controller.GraphicObject#drawSelfOn(swarm.gui.Raster)
	 */
	@Override
	public Object drawSelfOn(Raster raster) {
		raster.drawPointX$Y$Color(pos.x, pos.y, colorIndex);
		return this;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.edu.ufabc.va.acs.controller.GraphicObject#setColorIndex(byte)
	 */
	@Override
	public void setColorIndex(byte colorIndex) {
		this.colorIndex = colorIndex;
	}

}
